using System;
using System.Text;
using System.Collections.Generic;
using InfoJetSoft.Service.XPath;

//CID 0164 //2008.12.13 //Begin
namespace InfoJetSoft.Service.XPath.Exprs
{
	/// <summary>
	/// Summary description for RelativeLocationPath.
	/// </summary>
    public class RelativeLocationPath : IExpr
	{
		private List<IExpr> _stepList = null;

		public RelativeLocationPath()
		{
			//
			// TODO: Add constructor logic here
			//
        }

        public List<IExpr> Steps
        {
            get
            {
                return this._stepList;
            }
        }

        public object Evaluate(ExprContext context)
        {
            //CID 0814 //2011.03.01 //Begin
            object leftValue = null;
            for (int i = 0; i < this._stepList.Count; i++)
            {
                IExpr expr = this._stepList[i];
                if (expr is OperatorExpr)
                {
                    OperatorExpr oper = (OperatorExpr)expr;
                    if (oper.Operator == Operator.Slash)
                    {
                        context.Calculator.Slash(leftValue);
                    }
                    else if (oper.Operator == Operator.SlashSlash)
                    {
                        context.Calculator.SlashSlash(leftValue);
                    }
                    else
                    {
                        throw new Exception("Unsupported operator: " + oper.Operator);
                    }
                    i++;
                    IExpr nextExpr = this._stepList[i];
                    //CID 0909 //2011.05.15 //Begin
                    //O862 //Trace LastStep
                    if (i == (this._stepList.Count - 1))
                    {
                        context.Calculator.IsLastStep = true;
                    }
                    //CID 0909 //2011.05.15 //End
                    leftValue = nextExpr.Evaluate(context);
                    //CID 0909 //2011.05.15 //Begin
                    if (i == (this._stepList.Count - 1))
                    {
                        context.Calculator.IsLastStep = false;
                    }
                    //CID 0909 //2011.05.15 //End
                }
                else
                {
                    if (leftValue == null)
                    {
                        //CID 0909 //2011.05.15 //Begin
                        //O862 //Trace LastStep
                        if (this._stepList.Count == 1)
                        {
                            context.Calculator.IsLastStep = true;
                        }
                        //CID 0909 //2011.05.17 //End
                        leftValue = expr.Evaluate(context);
                        //CID 0909 //2011.05.15 //Begin
                        if (this._stepList.Count == 1)
                        {
                            context.Calculator.IsLastStep = false;
                        }
                        //CID 0909 //2011.05.17 //End
                    }
                    else
                    {
                        throw new Exception("Unsupported expr order");
                    }
                }
            }
            return leftValue;
            //CID 0814 //2011.03.01 //End
        }

        //CID 0866 //2011.04.01 //Begin
        public void Visit(IExprVisitor visitor)
        {
            for (int i = 0; i < this._stepList.Count; i++)
            {
                IExpr expr = this._stepList[i];
                expr.Visit(visitor);
            }
        }
        //CID 0866 //2011.04.01 //End

        public void Print(StringBuilder buffer)
        {
            foreach (IExpr expr in this._stepList)
            {
                expr.Print(buffer);
            }
        }

        public static IExpr Parse(ExprParser parser)
		{
			IExpr step = Step.Parse( parser );
			if( step != null )
			{
                List<IExpr> array = new List<IExpr>();
				array.Add( step );

                OperatorExpr separator = OperatorExpr.ParseStepSeparator(parser);
				while( separator != null )
				{
					array.Add( separator );

                    IExpr nextStep = Step.Parse(parser);
					if( nextStep == null )
					{
						throw new Exception( "Cannot parse " + parser.XPath );
					}
					array.Add( nextStep );
					
					separator = OperatorExpr.ParseStepSeparator( parser );
				}

                RelativeLocationPath relativeLocationPath = new RelativeLocationPath();
                relativeLocationPath._stepList = array;
                return relativeLocationPath;
			}
			return null;
		}
	}
}
//CID 0164 //2008.12.13 //End
